www.gusucode.com > 基于Visual C++高级界面特效制作百例源码程序 > 基于Visual C++高级界面特效制作百例源码程序/code/char22/XStatusBarProject/XStatusBar.cpp

    
#include "StdAfx.h"
#include "XStatusBar.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

volatile static char jrrcid[] = "%J%";

#define IDC_JRLIB_STATUSBAR_TIMER	20000

XPaneInfo::XPaneInfo()
{
	progress	= NULL;
	hScrollPos	= 0;
	vScrollPos	= 0;

	SetDefault();
}

XPaneInfo::XPaneInfo(const XPaneInfo& paneInfo)
{
	for (int i = 0; i < 2; i++)
	{
		fgColor[i]	= paneInfo.fgColor[i];
		bkColor[i]	= paneInfo.bkColor[i];
		string[i]	= paneInfo.string[i];
	}

	font			= paneInfo.font;
	mode			= paneInfo.mode;
	progress		= NULL;
	hScrollPos		= paneInfo.hScrollPos;
	vScrollPos		= paneInfo.vScrollPos;
}

XPaneInfo::~XPaneInfo()
{
	if (progress)	delete progress;
	progress = NULL; 
}

XPaneInfo XPaneInfo::operator=(const XPaneInfo& paneInfo)
{
	for (int i = 0; i < 2; i++)
	{
		fgColor[i]	= paneInfo.fgColor[i];
		bkColor[i]	= paneInfo.bkColor[i];
		string[i]	= paneInfo.string[i];
	}

	font			= paneInfo.font;
	mode			= paneInfo.mode;
	hScrollPos		= paneInfo.hScrollPos;
	vScrollPos		= paneInfo.vScrollPos;

	if (progress)	delete progress;
	progress = NULL; 

	return *this;
}

void XPaneInfo::SetDefault()
{
	bkColor[1]	= COLORREF(GetSysColor(COLOR_MENU));
	bkColor[0]	= bkColor[1];

	fgColor[1]	= GetSysColor(COLOR_MENUTEXT);
	fgColor[0]	= RGB(GetRValue(bkColor[1])/2, GetGValue(bkColor[1])/2, GetBValue(bkColor[1])/2);

	mode		= XSB_TEXT | DT_LEFT;
	SetFont(CFont::FromHandle((HFONT) GetStockObject(ANSI_VAR_FONT)));

	if (progress)	delete progress;
	progress = NULL; 
}

void XPaneInfo::SetFont(LPCSTR name, int size)
{
	CFont pointFont;
	pointFont.CreatePointFont(size, name);
	pointFont.GetLogFont(&font);
}

void XPaneInfo::SetMode(int newMode)
{
	if ((mode = newMode) & XSB_PROGRESS)
	{
		if (!progress)
		{
			UINT style = WS_VISIBLE | WS_CHILD;
			if (mode & XSB_SMOOTH) style |= PBS_SMOOTH;

			progress = new CProgressCtrl();
			progress->Create(style, CRect(0,0,0,0), XStatusBar::aktBar, 1);
		}
	}
	else if (progress)
	{
		delete progress;
		progress = NULL; 
	}
}

void XPaneInfo::SetFgColor(COLORREF on, COLORREF off)
{
	fgColor[1] = on;

	if (off != -1)
		fgColor[0] = off;
	else
	{
		COLORREF bk = GetSysColor(COLOR_MENU);
		fgColor[0] = RGB(GetRValue(bk)/2, GetGValue(bk)/2, GetBValue(bk)/2);
	}
}

void XPaneInfo::SetBkColor(COLORREF on, COLORREF off)
{
	bkColor[1] = on;
	if (off != -1)	bkColor[0] = off;
	else			bkColor[0] = GetSysColor(COLOR_MENU);
}

void XPaneInfo::SetBitmap(LPCSTR newOnBitmap, LPCSTR newOffBitmap)
{
	string[1]	= newOnBitmap;
	string[0]	= newOffBitmap;
}

void XPaneInfo::SetText(LPCSTR newOnText, LPCSTR newOffText)
{
	string[1]	= newOnText;
	string[0]	= newOffText;
}

void XPaneInfo::SetNumber(int newOnNumber, int newOffNumber)
{
	string[1].Format("%d", newOnNumber);
	string[0].Format("%d", newOffNumber);
}

void XPaneInfo::HScroll(CRect& rect, int maxWidth, int nullValue)
{
	if (++hScrollPos > maxWidth)	hScrollPos = nullValue;
	rect.left -= hScrollPos;
}

void XPaneInfo::VScroll(CRect& rect, int maxHeight, int nullValue)
{
	if (++vScrollPos > maxHeight)	vScrollPos = nullValue;
	rect.top -= vScrollPos;
}

#ifdef _DEBUG
	void XPaneInfo::Dump(CDumpContext& dc) const
	{
		dc	<< "FgColor / BkColor / Value:\t" 
			<< fgColor[1] << " - " << fgColor[0] << " / "
			<< bkColor[1] << " - " << bkColor[0] << " / "
			<< string[1]  << " - " << string[0]  << "\n"
			<< "Mode:\t"  << mode  << "\n";
	}

	void XPaneInfo::AssertValid() const
	{
		ASSERT((progress == NULL) || _CrtIsValidHeapPointer(progress));
	}

	CDumpContext& AFXAPI operator<<(CDumpContext& dc, XPaneInfo& paneInfo)
	{
		paneInfo.Dump(dc);
		return dc;
	}
#endif // _DEBUG

XStatusBar *XStatusBar::aktBar = NULL;

XStatusBar::XStatusBar()
{
	aktBar		= this;
	timerID		= 0;
}

XStatusBar::~XStatusBar()
{
}

BEGIN_MESSAGE_MAP(XStatusBar, CStatusBar)
	//{{AFX_MSG_MAP(XStatusBar)
	ON_WM_DESTROY()
	ON_WM_TIMER()
	ON_WM_PAINT()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MBUTTONDBLCLK()
	ON_WM_MBUTTONDOWN()
	ON_WM_MBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_RBUTTONDBLCLK()
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

bool XStatusBar::CreateStatusBar(CWnd *pWnd, const UINT* lpIDArray, int nIDCount, UINT pane0Style)
{
	bool ret = (Create(pParent = pWnd) &&
				SetIndicators(lpIDArray, nIDCount));

	if (ret)	SetStyle(0, pane0Style);
	else		AfxMessageBox("Unable to create Statusbar.");

	return ret;
}

BOOL XStatusBar::SetIndicators(const UINT* lpIDArray, int nIDCount)
{
	BOOL ret = CStatusBar::SetIndicators(lpIDArray, nIDCount);

	XPaneInfo defaultInfo;
	paneInfo.SetSize(nIDCount);
	
	for (int i = 0; i < nIDCount; i++)
		paneInfo[i] = defaultInfo;

	return ret;
}

void XStatusBar::OnPaint()
{
	CPaintDC	dc(this);
	CRect		client;		GetClientRect(client);
	CDC			memDC;		memDC.CreateCompatibleDC(&dc);
	CBitmap		bitmap;		bitmap.CreateCompatibleBitmap(&dc, client.Width(), client.Height());
	CBitmap		*oldBitmap	= (CBitmap *) memDC.SelectObject(&bitmap);
	COLORREF	hell		= GetSysColor(COLOR_3DHILIGHT);
	COLORREF	dunkel		= GetSysColor(COLOR_3DSHADOW);

	memDC.FillSolidRect(client, GetSysColor(COLOR_3DFACE));

	//========================================================================
	// Zeichne alle Pane-Rechtecke mit ihrem Inhalt
	//========================================================================
	bool scroll = false;
	for (int i = 0, n = paneInfo.GetSize(); i < n; i++)
	{
		XPaneInfo &aktPane = paneInfo[i];

		CRect	rect;
		GetItemRect(i, rect);
		UINT style = GetPaneStyle(i);

		if (style & SBPS_POPOUT)			memDC.Draw3dRect(rect, hell, dunkel);
		else if (!(style & SBPS_NOBORDERS))	memDC.Draw3dRect(rect, dunkel, hell);

		on = (GetPaneStyle(i) & SBPS_DISABLED) == 0;

		rect.DeflateRect(1, 1);
		memDC.FillSolidRect(rect, aktPane.GetBkColor(on));

		CRgn clip;
		clip.CreateRectRgnIndirect(&rect);
		memDC.SelectClipRgn(&clip);

		switch (aktPane.GetMode() & XSB_MODE)
		{
		case XSB_TEXT:
		case XSB_NUMBER:	DrawTextPane(	 &memDC, i, rect, aktPane);	break;
		case XSB_BITMAP:	DrawBitmapPane(	 &memDC, i, rect, aktPane);	break;
		case XSB_PROGRESS:	DrawProgressPane(&memDC, i, rect, aktPane);	break;
		default:														break;
		}

		if (aktPane.GetMode() & XSB_SCROLL)	scroll = true;

		memDC.SelectClipRgn(NULL);
	}

		 if (scroll  && (timerID == 0))		timerID = SetTimer(IDC_JRLIB_STATUSBAR_TIMER, 100, NULL);
	else if (!scroll && (timerID != 0))		{ KillTimer(timerID); timerID = 0; }

	if (!GetParent()->IsZoomed()) DrawSizing(&memDC);

	dc.BitBlt(0, 0, client.Width(), client.Height(), &memDC, 0, 0, SRCCOPY);

	memDC.SelectObject(oldBitmap);
}

void XStatusBar::DrawSizing(CDC *pDC)
{
	CRect rect;
	GetWindowRect(&rect);
	rect.OffsetRect(-rect.left, -rect.top);

	CPen hellPen(PS_SOLID, 1, GetSysColor(COLOR_3DHILIGHT));
	CPen dunkelPen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
	CPen *oldPen = pDC->SelectObject(&dunkelPen);
	for (int i = 1; i < 18; i++)
	{
		switch (i % 4)
		{
		case 0:		pDC->SelectObject(&dunkelPen);	break;
		case 1:		pDC->SelectObject(&hellPen);	break;
		case 2:		continue;
		case 3:		pDC->SelectObject(&dunkelPen);	break;
		}
		pDC->MoveTo(rect.right - i, rect.bottom);
		pDC->LineTo(rect.right,		rect.bottom - i);
	}

	pDC->SelectObject(oldPen);
}

void XStatusBar::DrawTextPane(CDC *pDC, int ix, CRect& rect, XPaneInfo& aktPane)
{
	CString		text		= aktPane.GetText(on);
	if (text.IsEmpty())		text = GetPaneText(ix);
	if (text.IsEmpty())		return;

	CFont		font;		font.CreateFontIndirect(&aktPane.GetFont());
	COLORREF	textColor	= aktPane.GetFgColor(on);
	CFont		*oldFont	= pDC->SelectObject(&font);
	int			oldBkMode	= pDC->SetBkMode(TRANSPARENT);
	COLORREF	oldFgColor	= pDC->SetTextColor(textColor);
	const int	mode		= aktPane.GetMode();
	const int	repeat		= mode & XSB_REPEAT;
	const int	hScroll		= mode & XSB_HSCROLL;
	const int	vScroll		= mode & XSB_VSCROLL;
	int			textAlign	= mode & XSB_ALIGN;
	if (hScroll)textAlign	&= ~(DT_CENTER | DT_RIGHT);

	if (repeat)
	{
		text += "  ";
		CSize s = pDC->GetTextExtent(text);
		if (hScroll)	aktPane.HScroll(rect, s.cx, 1);
		if (vScroll)	aktPane.VScroll(rect, s.cy, 1);

		int y = rect.top;
		if (hScroll && vScroll)
			for ( ; rect.left <= rect.right; rect.left += s.cx)
				for (rect.top = y ; rect.top <= rect.bottom; rect.top += s.cy)
					pDC->DrawText(text, rect, textAlign);
		else if (hScroll)
			for ( ; rect.left <= rect.right; rect.left += s.cx)
				pDC->DrawText(text, rect, textAlign);
		else if (vScroll)
			for ( ; rect.top <= rect.bottom; rect.top += s.cy)
				pDC->DrawText(text, rect, textAlign);
		else
			pDC->DrawText(text, rect, textAlign);
	}
	else
	{
		CSize s = pDC->GetTextExtent(text);
		if (hScroll)	aktPane.HScroll(rect, s.cx, -rect.Width());
		if (vScroll)	aktPane.VScroll(rect, s.cy, -rect.Height());

		pDC->DrawText(text, rect, textAlign);
	}

	pDC->SelectObject(oldFont);
	pDC->SetTextColor(oldFgColor);
	pDC->SetBkMode(oldBkMode);
}

void XStatusBar::DrawBitmapPane(CDC *pDC, int ix, CRect& rect, XPaneInfo& aktPane)
{
	CString		bmString	= aktPane.GetBitmap(on);
	if (bmString.IsEmpty())	return;
	CDC			memDC;		memDC.CreateCompatibleDC(pDC);
	CBitmap		bitmap;		bitmap.LoadBitmap(bmString);
	BITMAP		bm;			bitmap.GetBitmap(&bm);
	CBitmap		*oldBitmap	= memDC.SelectObject(&bitmap);
	const int	mode		= aktPane.GetMode();
	const int	hScroll		= mode & XSB_HSCROLL;
	const int	vScroll		= mode & XSB_VSCROLL;
	const int	repeat		= mode & XSB_REPEAT;
	const int	stretch		= mode & XSB_STRETCH;

	if (repeat)
	{
		if (hScroll)	aktPane.HScroll(rect, bm.bmWidth, 1);
		if (vScroll)	aktPane.VScroll(rect, bm.bmHeight, 1);

		if (hScroll && !vScroll)
			for (int x = rect.left; x < rect.right; x += bm.bmWidth)
				pDC->BitBlt(x, rect.top, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);
		else if (vScroll && !hScroll)
			for (int y = rect.top; y < rect.bottom; y += bm.bmHeight)
				pDC->BitBlt(rect.left, y, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);
		else
			for (int x = rect.left; x < rect.right; x += bm.bmWidth)
				for (int y = rect.top; y < rect.bottom; y += bm.bmHeight)
					pDC->BitBlt(x, y, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);

	}
	else
	{
		if (hScroll)	aktPane.HScroll(rect, bm.bmWidth, -rect.Width());
		if (vScroll)	aktPane.VScroll(rect, bm.bmHeight, -rect.Height());

		if (hScroll || vScroll)
			pDC->BitBlt(rect.left, rect.top, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);
		else if (stretch)
			pDC->StretchBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
		else
		{
			if (mode & DT_RIGHT)	rect.left	= rect.right - bm.bmWidth;
			if (mode & DT_CENTER)	rect.left	= (rect.left + rect.right - bm.bmWidth) / 2;
			if (mode & DT_BOTTOM)	rect.top	= rect.bottom - bm.bmHeight;
			if (mode & DT_VCENTER)	rect.top	= (rect.top + rect.bottom - bm.bmHeight) / 2;
			pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
		}
	}

	memDC.SelectObject(oldBitmap);
}

void XStatusBar::DrawProgressPane(CDC *pDC, int ix, CRect& rect, XPaneInfo& aktPane)
{
	rect.InflateRect(1, 1);
	GetProgressCtrl(ix)->MoveWindow(rect, FALSE);
}

XPaneInfo& XStatusBar::GetXPaneInfo(int ix)
{
	ASSERT(ix < GetCount());
	return paneInfo[ix];
}

void XStatusBar::OnTimer(UINT nIDEvent) 
{
	if (nIDEvent == timerID)	Invalidate(FALSE);
}

#define GET_PANE_INFO(ix)	ASSERT(ix < GetCount()); \
							UINT id, style; int width; \
							GetPaneInfo(ix, id, style, width)

UINT XStatusBar::SetStyle(int ix, UINT newStyle)	{ GET_PANE_INFO(ix); SetPaneInfo(ix, id, newStyle, width); return style; }
int  XStatusBar::SetWidth(int ix, int newWidth)		{ GET_PANE_INFO(ix); SetPaneInfo(ix, id, style, newWidth); return width; }
UINT XStatusBar::GetStyle(int ix)					{ GET_PANE_INFO(ix); return style;	}
int  XStatusBar::GetWidth(int ix)					{ GET_PANE_INFO(ix); return width;	}
UINT XStatusBar::GetID(int ix)						{ GET_PANE_INFO(ix); return id;	}

#undef GET_PANE_INFO

void XStatusBar::OnDestroy() 
{
	if (timerID)	KillTimer(timerID);
	timerID = 0;

	CStatusBar::OnDestroy();
}

void XStatusBar::SavePane(int ix)
{
	ASSERT(ix < GetCount());

	XPaneInfo	value;
	if (!buffer.Lookup(ix, value))
		buffer[ix] = paneInfo[ix];
}

void XStatusBar::RestorePane(int ix)
{
	ASSERT(ix < GetCount());
	
	XPaneInfo	value;
	if (buffer.Lookup(ix, value))
	{
		paneInfo[ix] = value;
		buffer.RemoveKey(ix);
	}

	Invalidate(FALSE);
}

int XStatusBar::GetPaneAtPosition(CPoint& point)
{
	if (pParent->IsKindOf(RUNTIME_CLASS(CDialog)))
	{
		pParent->ClientToScreen(&point);
		ScreenToClient(&point);
	}

	CRect rect;
	for (int i = 0, n = GetCount(); i < n; i++)
	{
		GetItemRect(i, rect);
		if (rect.PtInRect(point))	return i;
	}

	return -1;
}

#define TO_PARENT(fkt, event)	\
	void XStatusBar::fkt(UINT nFlags, CPoint point) \
	{ \
		pParent->SendMessage(event, (WPARAM) nFlags, MAKELPARAM(point.x, point.y)); \
		CStatusBar::fkt(nFlags, point); \
	}

TO_PARENT(OnLButtonUp,		WM_LBUTTONUP);
TO_PARENT(OnMButtonUp,		WM_MBUTTONUP);
TO_PARENT(OnRButtonUp,		WM_RBUTTONUP);
TO_PARENT(OnLButtonDown,	WM_LBUTTONDOWN);
TO_PARENT(OnMButtonDown,	WM_MBUTTONDOWN);
TO_PARENT(OnRButtonDown,	WM_RBUTTONDOWN);
TO_PARENT(OnLButtonDblClk,	WM_LBUTTONDBLCLK);
TO_PARENT(OnMButtonDblClk,	WM_MBUTTONDBLCLK);
TO_PARENT(OnRButtonDblClk,	WM_RBUTTONDBLCLK);
TO_PARENT(OnMouseMove,		WM_MOUSEMOVE);

#undef TO_PARENT